/*******************************************************************************
*	                           oled spi.c
*******************************************************************************/
#include "bsp.h"
#include "at32f435_437_spi.h"

#define OLED_SPI SPI1
#define ISR_IRQn SPI1_IRQn

/*****************************************************************************
* @brief   hal init.
*
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void oled_spi_init(void)
{
	spi_init_type cfg;
	intx_alloc();

	// 开启时钟
	intx_disable();

	crm_periph_clock_enable(CRM_SPI1_PERIPH_CLOCK, TRUE);
	crm_periph_reset(CRM_SPI1_PERIPH_RESET, TRUE);
	crm_periph_reset(CRM_SPI1_PERIPH_RESET, FALSE);

	intx_enable();

	// SPI 配置
	cfg.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
	cfg.mclk_freq_division = SPI_MCLK_DIV_32;
	cfg.master_slave_mode = SPI_MODE_MASTER;
	cfg.frame_bit_num = SPI_FRAME_8BIT;
	cfg.first_bit_transmission = SPI_FIRST_BIT_MSB;
	cfg.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
	cfg.clock_polarity = SPI_CLOCK_POLARITY_HIGH;
	cfg.clock_phase = SPI_CLOCK_PHASE_2EDGE;

	spi_init(OLED_SPI, &cfg);

	OLED_SPI->ctrl1_bit.spien = 1;
}

/*****************************************************************************
* @brief   cs ctr.
*
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void oled_spi_cs(uint8_t st)
{
	if (st)
	{
	}
	else
	{
	}
}

/*****************************************************************************
* @brief   spi speed.
*****************************************************************************/
void oled_spi_high_speed(void)
{
}

/*****************************************************************************
* @brief   spi speed.
*****************************************************************************/
void oled_spi_low_speed(void)
{
}

/*****************************************************************************
* @brief   spi delay.
*****************************************************************************/
#define spi_read_delay() NOP4()
#define is_spi_rx_ready() OLED_SPI->sts_bit.rdbf
#define spi_rx_reset()                       \
	while (is_spi_rx_ready())                \
	{                                        \
		volatile uint32_t rd = OLED_SPI->dt; \
	}
#define is_spi_busy() OLED_SPI->sts_bit.bf
#define spi_send(dat) OLED_SPI->dt = dat
#define is_spi_tx_full() (OLED_SPI->sts_bit.tdbe == 0)
#define is_spi_tx_empty() OLED_SPI->sts_bit.tdbe
#define spi_read() OLED_SPI->dt

/*****************************************************************************
* @brief   spi data read.
*****************************************************************************/
uint8_t oled_spi_rb(void)
{
	spi_rx_reset();

	//send data
	spi_send(0xFF);
	spi_read_delay();

	//wait for trans complete
	while (is_spi_busy())
		;

	//read data
	return (spi_read());
}

void oled_spi_wb(uint8_t dataW)
{
	volatile uint8_t rb;

	spi_rx_reset();

	//send data
	spi_send(dataW);
	spi_read_delay();

	//wait for trans complete
	while (is_spi_busy())
		;

	//read data
	rb = spi_read();
}

/*****************************************************************************
* @brief   spi data write.
*****************************************************************************/
uint8_t oled_spi_write(const uint8_t *dataw, uint32_t Len)
{
	while (Len--)
	{
		//send data
		spi_send(*dataw++);

		spi_read_delay();

		while (is_spi_tx_full())
		{
		}
	}

	spi_read_delay();

	//wait for trans complete
	while (is_spi_busy() || !is_spi_tx_empty())
	{
	}

	spi_rx_reset();

	return (0);
}

/*****************************************************************************
* @brief   spi data read.
*****************************************************************************/
uint8_t oled_spi_read(uint8_t *datar, uint32_t Len)
{
	uint32_t rcnt = 0;

	spi_rx_reset();

	while (Len--)
	{
		//send data
		spi_send(0xFF);

		spi_read_delay();

		while (!is_spi_rx_ready())
		{
		}

		datar[rcnt++] = spi_read();
	}

	return 0;
}
